home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / russell / gc.lha / headers.c < prev    next >
Text File  |  1993-03-04  |  6KB  |  212 lines

  1. /* 
  2.  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
  3.  * Copyright (c) 1991, 1992 by Xerox Corporation.  All rights reserved.
  4.  *
  5.  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  6.  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  7.  *
  8.  * Permission is hereby granted to copy this garbage collector for any purpose,
  9.  * provided the above notices are retained on all copies.
  10.  */
  11.  
  12. /*
  13.  * This implements:
  14.  * 1. allocation of heap block headers
  15.  * 2. A map from addresses to heap block addresses to heap block headers
  16.  *
  17.  * Access speed is crucial.  We implement an index structure based on a 2
  18.  * level tree.
  19.  * For 64 bit machines this will have to be rewritten.  We expect that the
  20.  * winning strategy there is to use a hash table as a cache, with
  21.  * collisions resolved through a 4 or 5 level tree.
  22.  */
  23.  
  24. # include "gc_private.h"
  25.  
  26. # if CPP_WORDSZ != 32
  27. #   if CPP_WORDSZ > 32
  28.      --> This needs to be reimplemented.  See above.
  29. #   else
  30.     --> Get a real machine.
  31. #   endif
  32. # endif
  33.  
  34. hdr ** GC_top_index [TOP_SZ];
  35.  
  36. typedef hdr * bottom_index[BOTTOM_SZ];
  37.  
  38. /*
  39.  * The bottom level index contains one of three kinds of values:
  40.  * 0 means we're not responsible for this block.
  41.  * 1 < (long)X <= MAX_JUMP means the block starts at least
  42.  *        X * HBLKSIZE bytes before the current address.
  43.  * A valid pointer points to a hdr structure. (The above can't be
  44.  * valid pointers due to the GET_MEM return convention.)
  45.  */
  46.  
  47. static bottom_index all_nils = { 0 };
  48.  
  49. /* Non-macro version of header location routine */
  50. hdr * GC_find_header(h)
  51. ptr_t h;
  52. {
  53.    return(HDR(h));
  54. }
  55.  
  56. /* Routines to dynamically allocate collector data structures that will */
  57. /* never be freed.                             */
  58.  
  59. static char * scratch_free_ptr = 0;
  60.  
  61. static char * scratch_end_ptr = 0;
  62.  
  63. ptr_t GC_scratch_alloc(bytes)
  64. register word bytes;
  65. {
  66.     register char * result = scratch_free_ptr;
  67.     scratch_free_ptr += bytes;
  68.     if (scratch_free_ptr <= scratch_end_ptr) {
  69.         return(result);
  70.     }
  71.     {
  72.         long bytes_to_get = ((HINCR+1) * HBLKSIZE + bytes) & ~(HBLKSIZE - 1);
  73.          
  74.         scratch_free_ptr = (char *)GET_MEM(bytes_to_get);
  75.         if (scratch_free_ptr == 0) {
  76.             GC_err_printf0("Out of memory - trying to allocate less\n");
  77.             result = (char *)GET_MEM(bytes);
  78.             if (result == 0) {
  79.                 GC_err_printf0("Out of memory - giving up\n");
  80.             } else {
  81.                 scratch_free_ptr -= bytes;
  82.                 return(result);
  83.             }
  84.         }
  85.         scratch_end_ptr = scratch_free_ptr + bytes_to_get;
  86.         return(GC_scratch_alloc(bytes));
  87.     }
  88. }
  89.  
  90. static hdr * hdr_free_list = 0;
  91.  
  92. /* Return an uninitialized header */
  93. static hdr * alloc_hdr()
  94. {
  95.     register hdr * result;
  96.     
  97.     if (hdr_free_list == 0) {
  98.         result = (hdr *) GC_scratch_alloc((word)(sizeof(hdr)));
  99.     } else {
  100.         result = hdr_free_list;
  101.         hdr_free_list = (hdr *) (result -> hb_next);
  102.     }
  103.     return(result);
  104. }
  105.  
  106. static void free_hdr(hhdr)
  107. hdr * hhdr;
  108. {
  109.     hhdr -> hb_next = (struct hblk *) hdr_free_list;
  110.     hdr_free_list = hhdr;
  111. }
  112.  
  113. GC_init_headers()
  114. {
  115.     register int i;
  116.      
  117.     for (i = 0; i < TOP_SZ; i++) {
  118.         GC_top_index[i] = all_nils;
  119.     }
  120. }
  121.  
  122. /* Make sure that there is a bottom level index block for address addr  */
  123. static void get_index(addr)
  124. register word addr;
  125. {
  126.     register word indx =
  127.             (word)(addr) >> (LOG_BOTTOM_SZ + LOG_HBLKSIZE);
  128.             
  129.     if (GC_top_index[indx] == all_nils) {
  130.         GC_top_index[indx] = (hdr **)
  131.                 GC_scratch_alloc((word)(sizeof (bottom_index)));
  132.         bzero((char *)(GC_top_index[indx]), (int)(sizeof (bottom_index)));
  133.     }
  134. }
  135.  
  136. /* Install a header for block h.  */
  137. /* The header is uninitialized.      */
  138. void GC_install_header(h)
  139. register struct hblk * h;
  140. {
  141.     get_index((word) h);
  142.     HDR(h) = alloc_hdr();
  143. }
  144.  
  145. /* Set up forwarding counts for block h of size sz */
  146. void GC_install_counts(h, sz)
  147. register struct hblk * h;
  148. register word sz; /* bytes */
  149. {
  150.     register struct hblk * hbp;
  151.     register int i;
  152.     
  153.     for (hbp = h; (char *)hbp < (char *)h + sz; hbp += BOTTOM_SZ) {
  154.         get_index((word) hbp);
  155.     }
  156.     get_index((word)h + sz - 1);
  157.     for (hbp = h + 1; (char *)hbp < (char *)h + sz; hbp += 1) {
  158.         i = hbp - h;
  159.         HDR(hbp) = (hdr *)(i > MAX_JUMP? MAX_JUMP : i);
  160.     }
  161. }
  162.  
  163. /* Remove the header for block h */
  164. void GC_remove_header(h)
  165. register struct hblk * h;
  166. {
  167.     free_hdr(HDR(h));
  168.     HDR(h) = 0;
  169. }
  170.  
  171. /* Remove forwarding counts for h */
  172. void GC_remove_counts(h, sz)
  173. register struct hblk * h;
  174. register word sz; /* bytes */
  175. {
  176.     register struct hblk * hbp;
  177.     
  178.     for (hbp = h+1; (char *)hbp < (char *)h + sz; hbp += 1) {
  179.         HDR(hbp) = 0;
  180.     }
  181. }
  182.  
  183. /* Apply fn to all allocated blocks */
  184. /*VARARGS1*/
  185. void GC_apply_to_all_blocks(fn, client_data)
  186. void (*fn)(/* struct hblk *h, word client_data */);
  187. word client_data;
  188. {
  189.     register int i, j;
  190.     register hdr ** index_p;
  191.     
  192.     for (i = 0; i < TOP_SZ; i++) {
  193.         index_p = GC_top_index[i];
  194.         if (index_p != all_nils) {
  195.             for (j = BOTTOM_SZ-1; j >= 0;) {
  196.                 if (!IS_FORWARDING_ADDR_OR_NIL(index_p[j])) {
  197.                   if (index_p[j]->hb_map != GC_invalid_map) {
  198.                     (*fn)(((struct hblk *)
  199.                             (((i << LOG_BOTTOM_SZ) + j) << LOG_HBLKSIZE)),
  200.                           client_data);
  201.                   }
  202.                   j--;
  203.                 } else if (index_p[j] == 0) {
  204.                   j--;
  205.                 } else {
  206.                   j -= (int)(index_p[j]);
  207.                 }
  208.             }
  209.         }
  210.     }
  211. }
  212.